#pragma once

#include <vector>
#include <string>
#include <algorithm>
class Buffer
{
public:
    static const size_t kCheapPrepend = 8; // 缓冲区的大小
    static const size_t kInitialSize = 1024; // 缓冲区的长度
    // onMessage string <- Buffer
    // 复位
    void retrieve(size_t len)
    {
        if (len < readableBytes())
        {
            readerIndex_ += len; // 应用只读取了可读缓冲区数据的一部分，就是len长度，还剩下readerIndex_ += len - writeIndex_;
        }
        else // len == readableBytes()
        {
            retrieveAll();
        }
    }

    explicit Buffer(size_t initialSize = kInitialSize)
        : buffer_(kCheapPrepend + initialSize), readerIndex_(kCheapPrepend), writeIndex_(kCheapPrepend)
    {
    }
    size_t readableBytes() const
    {
        return writeIndex_ - readerIndex_;
    }
    size_t writeableBytes() const
    {
        return buffer_.size() - writeIndex_;
    }

    size_t prependableBytes() const
    {
        return readerIndex_;
    }
    // 把[data, data+len]内存上的数据，添加到writable缓冲区当中
    void append(const char *data, size_t len)
    {
        ensureWriteableBytes(len);
        std::copy(data, data + len, beginWrite());
        writeIndex_ += len;
    }

    // 从fd上读取数据
    size_t readFd(int fd, int *saveErrno);
    // 通过fd发送数据
    size_t writeFd(int fd, int *saveError);

    std::string retrieveAllAsString()
    {
        return retrieveAsString(readableBytes()); // 应用可读取长度
    }

   

private:
    char *begin()
    {
        return (char *)&*buffer_.begin();
    }
    const char *begin() const
    {
        return &*buffer_.begin();
    }
    // 返回可读数据缓冲区的空间起始地址
    const char *peek() const
    {
        return begin() + readerIndex_;
    }
    
    std::string retrieveAsString(size_t len)
    {
        std::string result(peek(), len);
        // 上面把缓冲区冲可以读取的数据放在result，这里是对缓冲区进行复位操作
        retrieve(len);
        return result;
    }
    
    char *beginWrite()
    {
        return begin() + writeIndex_;
    }

    const char *beginWrite() const
    {
        return begin() + writeIndex_;
    }

    void retrieveAll()
    {
        // 相当于中间可读的都被读完了
        readerIndex_ = writeIndex_ = kCheapPrepend;
    }

    void makeSpace(size_t len)
    {
        if (writeableBytes() + prependableBytes() < len + kCheapPrepend)
        {
            buffer_.resize(writeIndex_ + len);
        }
        else
        {
            size_t readable = readableBytes();
            std::copy(begin() + readerIndex_, begin() + writeIndex_, begin() + kCheapPrepend);
            readerIndex_ = kCheapPrepend;
            writeIndex_ = readerIndex_ + readable;
        }
    }
    // buffer_.size - writeIndex_   len
    void ensureWriteableBytes(size_t len)
    {
        if (writeableBytes() < len)
        {
            makeSpace(len); // 扩容函数
        }
    }
    std::vector<char> buffer_;
    size_t readerIndex_;
    size_t writeIndex_;
};